
package event_classes;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Random;


public class EventController {
    private int simTime;
    private int nFrames;
    private long seed;
    private Comparator<Event> comparator;
    private PriorityQueue<Event> eventQueue;
    private float hRatio;
    private float mRatio;
    private float lRatio;
    private float freqTx;

    
    public EventController() {
        this.simTime = 0;
        this.nFrames = 0;
        this.comparator = new ScheduleComparator();
        this.eventQueue = new PriorityQueue();
        this.hRatio = 0;
        this.mRatio = 0;
        this.lRatio = 0;
        this.freqTx = 0;
    }
    
    public EventController(long seed, int nFrames, float hRatio, float mRatio, float lRatio, float freqTx) {
        this.simTime = 0;
        this.nFrames = nFrames;
        this.seed = seed;
        this.comparator = new ScheduleComparator();
        this.eventQueue = new PriorityQueue(60, comparator);
        this.hRatio = hRatio;
        this.mRatio = mRatio;
        this.lRatio = lRatio;
        this.freqTx = freqTx;
    }
    
    
    public void initEvents() {
        Random rand = new Random(this.seed);
        int tmp;
        int randNum;
        boolean chkr[] = new boolean[this.nFrames*2]; //for uniqueness
        
        for (int i = 0; i < chkr.length; i++) {
            chkr[i] = false; //means number is available
        }
        
        //Tx
        tmp = Math.round(this.nFrames * this.getFreqTx());
        for (int i = 0; i < tmp; i++) {
            randNum = rand.nextInt(chkr.length);
            
            while (chkr[randNum]) //while number is taken
                randNum = rand.nextInt(chkr.length);
            
            chkr[randNum] = true;
            
            if ( !this.eventQueue.offer( new Event( 0, randNum)) ) {
                System.out.println("Could not queue Event"); //for testing
            }
        }
        
        for (int i = 0; i < chkr.length; i++) {
            chkr[i] = false; //means number is available
        }
        
        //high
        tmp = Math.round(this.nFrames * this.gethRatio());
        for (int i = 0; i < tmp; i++) {
            randNum = rand.nextInt(chkr.length);
            
            while (chkr[randNum]) //while number is taken
                randNum = rand.nextInt(chkr.length);
            
            chkr[randNum] = true;
            
            if ( !this.eventQueue.offer( new Event( 1, randNum)) ) {
                System.out.println("Could not queue Event"); //for testing
            }
        }
        
        for (int i = 0; i < chkr.length; i++) {
            chkr[i] = false; //means number is available
        }
        
        //mid
        tmp = Math.round(this.nFrames * this.getmRatio());
        for (int i = 0; i < tmp; i++) {
            randNum = rand.nextInt(chkr.length);
            
            while (chkr[randNum]) //while number is taken
                randNum = rand.nextInt(chkr.length);
            
            chkr[randNum] = true;
            
            if ( !this.eventQueue.offer( new Event( 2, randNum)) ) {
                System.out.println("Could not queue Event"); //for testing
            }
        }
        
        for (int i = 0; i < chkr.length; i++) {
            chkr[i] = false; //means number is available
        }
        
        //low
        tmp = Math.round(this.nFrames * this.getlRatio());
        for (int i = 0; i < tmp; i++) {
            randNum = rand.nextInt(chkr.length);
            
            while (chkr[randNum]) //while number is taken
                randNum = rand.nextInt(chkr.length);
            
            chkr[randNum] = true;
            
            if ( !this.eventQueue.offer( new Event( 3, randNum)) ) {
                System.out.println("Could not queue Event"); //for testing
            }
        }
        
        //for testing
        //printEventsInQueue();
    }
    
    //for testing
    public void printEventsInQueue() {
        PriorityQueue<Event> testPQ = this.eventQueue;
        Event e = (Event)testPQ.poll();
        
        System.out.println(testPQ.size());
        
        
        while (e != null) {
            System.out.println(e.getId());
            e = (Event)testPQ.poll();
        }
        
        System.out.println(testPQ.size());
    }
    
    public void parseEventQueue() {
       
    }
    
    
    public Event pollEventQueue() {
        return this.eventQueue.poll();
    }
    
    public void moveToTime(int simTime) {
        setSimTime(simTime);
    }
    
    public void skipTime(int timeInterval) {
        this.simTime += timeInterval;
    }
    
    public int getSimTime() {
        return simTime;
    }
    
    public void incSimTime () {
        this.simTime++;
    }

    public void setSimTime(int simTime) {
        this.simTime = simTime;
    }

    public long getSeed() {
        return seed;
    }

    public void setSeed(long seed) {
        this.seed = seed;
    }

    public float gethRatio() {
        return hRatio;
    }

    public void sethRatio(float hRatio) {
        this.hRatio = hRatio;
    }

    public float getmRatio() {
        return mRatio;
    }

    public void setmRatio(float mRatio) {
        this.mRatio = mRatio;
    }

    public float getlRatio() {
        return lRatio;
    }

    public void setlRatio(float lRatio) {
        this.lRatio = lRatio;
    }

    public float getFreqTx() {
        return freqTx;
    }

 
    public void setFreqTx(float freqTx) {
        this.freqTx = freqTx;
    }

    
        private class ScheduleComparator implements Comparator<Event> {
            public int compare (Event e1, Event e2) {
                if ( e1.getSchedule() < e2.getSchedule() )
                    return -1;
                if ( e1.getSchedule() > e2.getSchedule() ) 
                    return 1;
                return 0;
            }
            
            public int compare (int x, int y) {
                if (x < y)
                    return -1;
                if (x > y)
                    return 1;
                return 0;
            }
        }
}
